/**
 *  \file I3Trigger.h
 *  \brief Declares an I3 Trigger and the functions to manipulate it.
 */

#ifndef I3_TRIGGER_CPP_H
#define I3_TRIGGER_CPP_H 1

extern "C" {
    #include "i3.h" 
    #include "i3_client_api.h"
}

#include <map>
#include <string>
using namespace std;

class I3Address;
class I3Packet;
class I3Key;
class I3Id;
class I3OCDStateInfo;
class I3OverlayNetwork;
class I3TimerEvent;
class I3Functor;
class I3Overlay;

class VirtualNode;

/** This class defines an I3 trigger. 
  */
class I3Trigger {

    map<int, I3Functor*> callbackMap;
    
    I3Functor* I3Trigger::lookupCallback(int callbackType);

    /** Maximum number of connections on this trigger - relevant only for public triggers. */
    int maxConn;
    /** Maximum bandwidth of traffic through this trigger */
    int maxBW;

public:

    /** "public" or "private" 
      * If the value of this field is "public", it means that this is a public trigger
      * with its public bit not set.  This happens when public triggers are formed by 
      * hashing the names.
      */
    string triggerType;
    
    /** The i3 key of the trigger */
    I3Key* i3Key;

    /** The i3 id of the trigger. */
    I3Id* i3Id;

    /** The cl_trigger being wrapped around */
    cl_trigger* cl_trig;

    /** The option type when the i3 trigger was received. */
    int optType;

    /** Is this an anycast trigger? */
    bool isAnycastFlag;
    
    /** This flag is set to indicate that this trigger needs to be destroyed.
      * This is usually used only for private triggers.  When the VN which inserted
      * a private trigger is destroyed, we cannot immediately free up the private trigger as
      * it may still be on the trigger refresh queue.  So the trigger is freed the next
      * time a trigger refresh event occurs if this flag is set to true. 
      */
    bool killMeFlag;
    
    /** The ocd state associated with this trigger.
      * Used when callback on this trigger is invoked.
      */
    I3OCDStateInfo* ocdState;

    /** The i3 overlay to which this trigger belongs.  Should match with ocdState->overlayToUse
      * if ocdState is not NULL.
      */
    I3OverlayNetwork *i3Overlay;
    
    /** The number of attempts made to insert this trigger. */
    int insertAttemptsCount;

    /** The trigger insertion timeout event.  We have to deactivate this event if
      * the trigger insert was successful.
      */
    I3TimerEvent* trigInsertTimer;

    /** A general purpose timer for this trigger */
    I3TimerEvent* timer;
    
    

    //function definitions
    
    I3Trigger(I3OverlayNetwork *);
    I3Trigger(cl_trigger* trig, int optType, I3OverlayNetwork*);
    I3Trigger(ID *id, I3OverlayNetwork *);

    void setI3Id(ID *);
    void doCallbacks(int eventType, cbk_packet *);
   
    void clearCallbacks ();

    void registerCallback(I3Functor *, int callbackType);
    bool isPublic();
    bool isPrivate();
    bool isAnycast();
    
    void createNewBlankId();


    virtual ~I3Trigger();

    void setRateLimit (int maxConn, int maxBW);

    static uint64_t getRandomTriggerRefreshInterval();
    
    friend class I3ClientContext;
    friend class I3OverlayNetwork;
};

#endif

